<!--甘特图首页-->
<template>
	<div class="gantt-table">
		<div class="gantt-head">
			<!-- 头部-->
			<div class="gantt-fixed">
				<div class="gantt-head">
					<span>时间区间</span>
					<span>{{ `${choiceTime[0].format('yyyy-MM-dd')} - ${choiceTime[1].format('yyyy-MM-dd')}` }}</span>

					<button @click="save">保存</button>
					<button @click="_hisBack">撤回</button>
				</div>
			</div>
		</div>
		<div class="gantt-box">
			<div class="left" ref="left">
				<div class="head">
					<!--    左边栏的列表头      -->
					<div class="head-box">
						<GanttRow>
							<!-- <GanttBlock>置顶</GanttBlock> -->
							<GanttBlock>序号</GanttBlock>
							<GanttBlock>机型</GanttBlock>
							<GanttBlock>机号</GanttBlock>
							<GanttBlock>布局</GanttBlock>
						</GanttRow>
					</div>
				</div>
				<!--  左边栏的列表内容      -->
				<div class="left-box" :style="{ transform: `translateY(-${transFormYValue}px)` }">
					<GanttRow v-for="(item, index) in ganttData" :key="index">
						<!-- <GanttBlock>💢</GanttBlock> -->
						<GanttBlock :style="MergeStyle('typeName', item.typeName, index)">{{ item.typeName }}</GanttBlock>
						<GanttBlock>{{ item.type }}</GanttBlock>
						<GanttBlock>{{ item.code }}</GanttBlock>
						<GanttBlock></GanttBlock>
					</GanttRow>
				</div>
			</div>
			<!--    右边的内容      -->
			<div class="right" ref="right">
				<!--  时间头      -->
				<div class="head">
					<div class="head-box">
						<GanttRow :style="{ transform: `translatex(-${transFormXValue}px)` }" class="transition-transForm">
							<GanttTimeBlock :target-time="item.format('yyyy-MM-dd')" v-for="(item, index) in choiceTimeArr" :key="index"></GanttTimeBlock>
						</GanttRow>
					</div>
				</div>
				<div class="content" ref="contentGrid">
					<!--      甘特图中具体的内容   -->
					<div class="gantt-grid" ref="box">
						<!--   网格状图表  -->
						<GanttRow
							v-for="(item, rowIndex) in ganttData"
							:key="rowIndex"
							:id="`ganttRow-${rowIndex}`"
							class="gantt-row-relative"
							:class="{ 'gantt-row-active': nowSuck === rowIndex }"
						>
							<template v-if="item.timeBlock">
								<div
									class="time-block gantt-grab"
									:class="' block-type-' + times.statu"
									@mousedown="onMouseDown($event, index, rowIndex)"
									@contextmenu.prevent="() => {}"
									@click.stop="onClicked(times)"
									v-for="(times, index) in item.timeBlock"
									:key="`times-${index}`"
									:style="timeBlockStyle(times)"
								>
									{{ times.name }}
									<!-- <span class="gantt-grab" style="font-size: 14px;padding-left: 10px;"></span> -->
								</div>
							</template>
							<!--      block => 180  因为timeBlock => 60    60*3 = 180px   -->
							<GanttBlock class="time" v-for="rowIndex in (24 / 12) * choiceTimeArr.length" :key="rowIndex" style="flex-shrink: 0"></GanttBlock>
						</GanttRow>
					</div>
				</div>
			</div>
		</div>
	</div>
</template>

<script>
import GanttRow from '@/components/gantt-v/gantt-row';
import GanttBlock from '@/components/gantt-v/gantt-block';
import GanttTimeBlock from '@/components/gantt-v/gantt-time-block';
import ganttMix from '@/components/gantt-v/gantt-mix.js';
import ganttHisMix from '@/components/gantt-v/gantt-his-mix.js';

import airPlaneData from '@/fake-data/airPlaneData.js';

export default {
	name: 'gantt-index',
	components: { GanttBlock, GanttRow, GanttTimeBlock },
	mixins: [ganttMix, ganttHisMix],
	data() {
		return {
			//用right 的滚动，控制aside-left的滚动
			transFormYValue: 0,
			//用right 的滚动，控制head-left的滚动
			transFormXValue: 0,
			//飞机的数据，用于渲染左侧边
			ganttData: airPlaneData,
			//选择的时间区间
			choiceTime: [new Date('2022-04-13 00:00:00'), new Date('2022-04-23 00:00:00')],
			defaultTop: 10,
			nowSuck: -1
		};
	},
	computed: {
		//通过选择的时间区间，得到这区间之间的数组
		choiceTimeArr() {
			let timeArr = [];
			//时间戳毫秒为单位
			//尾时间-首时间 算出头尾的时间戳差  再换算成天单位                                   毫秒->分->时->天
			let diffDays = (this.choiceTime[1].getTime() - this.choiceTime[0].getTime()) / 1000 / 60 / 60 / 24;

			//一天的时间戳
			let oneDayMs = 24 * 60 * 60 * 1000;
			//差了多少天就便利多少天 首时间+当前便利的天数的毫秒数
			for (let i = 0; i < diffDays + 1; i++) {
				//时间戳来一个相加，得到的就是时间数组
				timeArr.push(new Date(this.choiceTime[0].getTime() + i * oneDayMs));
			}

			console.log(diffDays, oneDayMs, timeArr);
			return timeArr;
		}
	},
	methods: {
		//滚动事件
		getScrollEvent() {
			let rightDom = this.$refs.contentGrid;
			rightDom.addEventListener('scroll', e => {
				let scrollLeft = e.target.scrollLeft;
				let scrollTop = e.target.scrollTop;
				this.transFormYValue = scrollTop;
				this.transFormXValue = scrollLeft;
			});

			let leftDom = this.$refs.left;
			leftDom.addEventListener('mousewheel', e => {
				let wheelValue = e.deltaY;
				rightDom.scrollTop += wheelValue;
			});
		},

		/**
		 * 当对于这个时间块按下的时候
		 * @param e 时间块的 event 事件
		 * @param index 时间块的索引
		 * @param rowIndex 该条线的id
		 */
		onMouseDown(e, index, rowIndex) {
			//用box 移动，不采用 Doucment
			let box = this.$refs.box;
			let dom = e.target;
			// 算出鼠标相对元素的位置
			let disX = e.clientX - dom.offsetLeft;
			let disY = e.clientY - dom.offsetTop;

			//当点击下来的时候 nowSuck 其实等于的就是当前index
			this.nowSuck = rowIndex;

			//让本来拥有手掌样式的class取消
			dom.classList.remove('gantt-grab');
			//让整个box 鼠标都是抓住
			box.classList.add('gantt-grabbing');

			//如果事件绑定在 dom上，那么一旦鼠标移动过快就会脱离掌控
			box.onmousemove = ee => {
				//获得当前受到拖拽的div 用于计算suck 所谓拖引的行数
				let top = parseInt(dom.style.top);
				//四舍五入 获得磁性吸附激活的值 (索引值)  60是block的height 10是时间块距离block的top  suck 可以当作row的索引
				let suck = Math.round((top - 10) / 60) + rowIndex;

				//suck的边界值设置
				if (suck < 0) {
					suck = 0;
				} else if (suck > this.ganttData.length - 1) {
					suck = this.ganttData.length - 1;
				}

				//suck 行样式变化
				this.nowSuck = suck;

				//移动事件
				this.onMouseMove(ee, disX, disY, dom);
			};
			//不管在哪里，鼠标松开的时候，清空事件 所以对于这个 “不管在哪里，使用了window”
			window.onmouseup = () => {
				//鼠标松开了，让时间块恢复手掌样式
				dom.classList.add('gantt-grab');
				//整个box 不在抓住了，变成箭头鼠标
				box.classList.remove('gantt-grabbing');

				this._addHisList(this.ganttData);

				let oldTimeBlock = this.ganttData[rowIndex].timeBlock[index];
				//let timeId = oldTimeBlock.id;

				// startTime 与 endTime 用于数据重新替换  上面css已经经过计算 1px 等于1分钟  60分钟等于1小时
				let startTime = new Date(this.choiceTime[0].getTime() + parseInt(dom.style.left) * 240 * 1000);
				let endTime = new Date(this.getTime(startTime) + parseInt(dom.style.width) * 240 * 1000);
				//console.log(startTime, endTime, dom.style.width, parseInt(dom.style.left) * 60 * 1000);
				let suck = this.nowSuck;

				//加入新数据
				let data = oldTimeBlock;
				this.$set(data, 'startTime', startTime);
				this.$set(data, 'endTime', endTime);
				// data.startTime = startTime;
				// data.endTime = endTime;

				/**
				 * 本来dom元素磁性吸附是打算用document.appendChild() 方式来做的，但是对于vue来说 for出来的子元素就算变了位置，其index也不属于新的row
				 */
				//老数据 删除
				this.ganttData[rowIndex].timeBlock.splice(index, 1);

				//新数据加入
				this.ganttData[suck].timeBlock.push(data);

				//坐标定位 磁性吸附 永远的10px   不知道为啥动态绑定的元素也会受到以前元素的影响，可能是 for 中 index带来的影响
				dom.style.top = this.defaultTop + 'px';

				//松开鼠标的时候 清空
				box.onmousemove = null;
				window.onmouseup = null;

				//需要重新计算吸附位置,以及整行重新排列
				this.$nextTick(() => {
					this.calcTime(data, this.ganttData[suck].timeBlock);
				});

				//将当前row 清空
				this.nowSuck = -1;

				//改变位置后回调事件
				this.afterChangePosition(data, this.ganttData[rowIndex].id, this.ganttData[suck].id);
			};
		},

		// 时间块点击
		onClicked(time) {
			console.log('点击:', time);
		},

		/**
		 * 鼠标移动的时候，前置条件鼠标按下
		 * @param e 时间块的 event 事件
		 * @param disX x轴
		 * @param disY y轴
		 * @param targetDom 时间块的dom 其实可以直接 e.target 获取
		 */
		onMouseMove(e, disX, disY, targetDom) {
			// 用鼠标的位置减去鼠标相对元素的位置，得到元素的位置
			let left = e.clientX - disX;
			let top = e.clientY - disY;

			//移动距离不能小于零(开始时间)
			if (left < 0) {
				left = 0;
			}

			targetDom.style.left = left + 'px';
			targetDom.style.top = top + 'px';
		},
		/**
		 * 时间块位置变化后回调事件
		 * @param data 时间块的值 包括时间块id startTime endTime
		 * @param rowOId 时间块原来所在的那个飞机id (一条横线)
		 * @param rowNId 时间块新的所在的那个飞机id
		 */
		afterChangePosition(data, rowOId, rowNId) {
			console.log('afterChangePosition', data, rowOId, rowNId);
		},

		save() {
			console.log(JSON.stringify(this.ganttData));
		}
	},
	mounted() {
		this.getScrollEvent();
		console.log(new Date('2022-04-13 00:00:00').getDate());
	}
};
</script>

<style scoped lang="scss">
@import '~@/components/gantt-v/css/gant-v.scss';
</style>
